package com.wenlin.userservice.lock;

import com.wenlin.userservice.exception.TryLockTimeOutException;
import com.wenlin.userservice.response.Message;
import com.wenlin.userservice.util.SpringContextUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/***
 *  Created with IntelliJ IDEA.
 *  Author:  wenlin
 *  Date:  2018/3/26 15:48
 *  Description:
 **/
@Service
public class RedissonService {
    private static Logger logger = LoggerFactory.getLogger(RedisService.class);
    @Autowired
    private RedissonClient redissonClient;

    //可重入锁
    public Message setLock() {
        RLock lock = redissonClient.getLock("Lock");
        String result = null;
        try {
            // 1. 最常见的使用方法
            // lock.lock();
            // 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁
            // lock.lock(10, TimeUnit.SECONDS);
            // 3. 尝试加锁，最多等待3秒，上锁以后10秒自动解锁
            boolean res = lock.tryLock(3, 20, TimeUnit.SECONDS);
            if (res) { //成功 // do your business
                result = "获取资源所";
                logger.info("加锁成功");
            } else {
                result = "暂无资源,请等待";
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //lock.unlock();
        }
        return new Message(result);
    }

    public Message setLockAsync() {
        RLock lock = redissonClient.getLock("Lock");
        String result = null;
        try {
            lock.lockAsync();
            lock.lockAsync(10, TimeUnit.SECONDS);
            Future<Boolean> res = lock.tryLockAsync(3, 10, TimeUnit.SECONDS);
            if (res.get()) { //成功 // do your business
                result = "获取资源所";
                logger.info("加锁成功");
            } else {
                result = "暂无资源,请等待";
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return new Message(result);
    }

    public String unLock() {
        RLock lock = redissonClient.getLock("Lock");
        lock.unlock();
        return "解锁操作已执行";
    }

    /***
     *  Author:  wenlin
     *  Date:  2018/3/26
     *  Description:公平锁
     **/
    public Message setfairLock() {
        RLock fairLock = redissonClient.getFairLock("FairLock");
        String result = null;
        try {
            // 最常见的使用方法
            // fairLock.lock();
            // 支持过期解锁功能, 10秒钟以后自动解锁,无需调用unlock方法手动解锁
            //fairLock.lock(10, TimeUnit.SECONDS);
            // 尝试加锁，最多等待100秒，上锁以后10秒自动解锁
            Long id = Thread.currentThread().getId();
            String name = Thread.currentThread().getName();
            //logger.info("线程id：" + id + "线程名字：" + name + "请求加锁");
            boolean res = fairLock.tryLock(100, 5, TimeUnit.SECONDS);
            if (res) {
                /*Long id = Thread.currentThread().getId();
                String name = Thread.currentThread().getName();*/
                logger.info("线程id：" + id + "线程名字：" + name + " 加锁成功");
                result = "获取资源，执行业务";
            } else {
                result = "等待锁";
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //fairLock.unlock();
        }
        return new Message(result);
    }


    public Boolean setAnnationLock(String value) {
        RLock lock = redissonClient.getLock(value);
        boolean res = false;
        try {
            // 1. 最常见的使用方法
            // lock.lock();
            // 2. 支持过期解锁功能,10秒钟以后自动解锁, 无需调用unlock方法手动解锁
            // lock.lock(10, TimeUnit.SECONDS);
            // 3. 尝试加锁，最多等待3秒，上锁以后10秒自动解锁
            res = lock.tryLock(3, 100, TimeUnit.SECONDS);
            if (res) { //成功 // do your business
                logger.info("加锁成功");
                Thread.sleep(1000);
            } else {
                throw new TryLockTimeOutException();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } /*finally {
            lock.unlock();
        }*/
        return res;
    }

    public void annationUnLock(String value) {
        RLock lock = redissonClient.getLock(value);

        lock.unlock();
    }

    @Lock("order")
    public void order() {
        System.out.println("生成流水号:" + System.currentTimeMillis() / 1000);
        //通过spring上下文获取bean,异步调用gen方法
        RedissonService service = SpringContextUtils.getBean(RedissonService.class);
        String type1= "springBean";
        String type2= "thisBean";
        for (int i = 0; i < 10; i++) {
            new Thread(()->service.gen(type1), "springBean" + i).start();
        }
        //直接多线程异步调用gen方法
        for (int i = 0; i < 10; i++) {
            new Thread(()->this.gen(type2), "thisBean" + i).start();
        }
        //gen();
    }

    @Lock("order")
    public void gen(String type) {
        System.out.println(type+"生成流水号:" + System.currentTimeMillis() / 1000);
    }
}
